#! /usr/bin/env python
# -*- coding: utf-8 -*-

import time
import socket
from gevent import monkey
monkey.patch_all()
import sys
import operator
import lxml.html

import requests


timeout = 30
socket.setdefaulttimeout(timeout)

filename = sys.argv[1]
# type:socks5 http connect and so on
t = sys.argv[2]
save_file_anonymous = './anonymous/' + t + '_proxy_anonymous.txt'
save_file_useful = './useful/' + t + '_proxy_useful.txt'

anonymous_proxy_list = {}
useful_proxy_list = {}

with open(filename) as f:
    result = f.readlines()
    # 把换行去掉
    print "[^] There are %s proxies to try" % len(result)
    for i in range(len(result)):
        result[i] = result[i].strip()

# print result


def check(url, proxy, ip, t):
    if t == 'http':
        check_http(url, proxy, ip)
    elif t == 'https':
        check_connect(url, proxy, ip)
    elif t == 'socks5':
        check_socks5(url, proxy, ip)


def check_socks5(url, proxy, ip):
    """docstring for check_connect"""
    try:
        address = proxy.split(':')
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        t1 = time.time()
        s.connect((address[0], int(address[1])))
        data = '\x05\x01\x00\x0a'
        s.sendall(data)
        ret = s.recv(25)
        t2 = time.time()
        if ret[:2] == '\x05\x00':
            useful_proxy_list[proxy] = t2 - t1
    except:
        pass


def check_http(url, proxy, ip):
    """docstring for check"""
    proxy_dict = {"http": "http://" + proxy}
    try:
        # print "[*] Trying proxy: %s" % proxy
        r = requests.get(url, proxies=proxy_dict, timeout=4, stream=True)
        if r.ok:
            assert r.content.find("Proxy Checker") >= 0
            useful_proxy_list[proxy] = r.elapsed.total_seconds()
            if r.content.find(ip) == -1:
                anonymous_proxy_list[proxy] = r.elapsed.total_seconds()
                # print "[++] Proxy %s anonymous" % proxy
            else:
                # print "[+] Proxy %s works but not anonymous" % proxy
                pass
    except:
        # print "[-] Proxy %s NOT work" % proxy
        pass


def check_connect(url, proxy, ip):
    """docstring for check_connect"""
    try:
        address = proxy.split(':')
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        t1 = time.time()
        s.connect((address[0], int(address[1])))
        s.sendall("CONNECT google.com:443 HTTP/1.1\r\n\
                  User-Agent: Mozilla/5.0 \
                  (X11; Linux x86_64; rv:24.0) \
                  Gecko/20100101 Firefox/24.0\r\n\
                  Proxy-Connection: keep-alive\r\n\
                  Connection: keep-alive\r\n\
                  Host: google.com\r\n\r\n")
        ret = s.recv(25)
        t2 = time.time()
        if ret.find('200') >= 0:
            useful_proxy_list[proxy] = t2 - t1
    except:
        pass


def get_real_ip(url="http://iframe.ip138.com/ic.asp"):
    """docstring for get_real_ip"""
    try:
        r = requests.get(url, timeout=5)
        if r.ok:
            # ip = re.findall(r'\d+\.\d+\.\d+\.\d+', r.content)[0]
            root = lxml.html.fromstring(r.content)
            ip = root.xpath('//td/div[3]/p/span[2]/text()')[0]
            print "[!] Your ip is %s" % ip
            return ip
    except:
        # print e
        print "[!]Can't find ip"
        sys.exit(0)


url = "http://www.iprivacytools.com/proxy-checker-anonymity-test/"
# url = "http://twitter.com"
ip = get_real_ip(url)
i = 0
# jobs = [gevent.spawn(check, url, proxy, ip, t) for proxy in result]
# gevent.joinall(jobs)  # , timeout=300)
#from gevent.pool import Pool


def check_2(proxy):
    """docstring for check_2"""
    check(url, proxy, ip, t)
    global i
    i += 1
    sys.stdout.write('\r')
    sys.stdout.write("[%s%s] %0.2f %%" %
                     ('#' * int(100 * float(i) / len(result)),
                      '.' * (100 - int(100 * float(i) / len(result))),
                      100 * float(i) / len(result)))
    sys.stdout.flush()
# import gevent
# jobs = [gevent.spawn(check_2, proxy) for proxy in result]
# gevent.joinall(jobs, timeout=300)
from gevent.pool import Pool
pool = Pool(100)
# pool.join(timeout=300)
pool.map(check_2, result)

if t == 'http':
    sorted_anonymous_proxy_list = sorted(anonymous_proxy_list.iteritems(),
                                         key=operator.itemgetter(1))
    sorted_useful_proxy_list = sorted(useful_proxy_list.iteritems(),
                                      key=operator.itemgetter(1))
    # write anonymous proxies
    with open(save_file_anonymous, 'wb') as f:
        for proxy, elapsed in sorted_anonymous_proxy_list:
            # print proxy, elapsed
            f.write(proxy + '\n')

elif t == 'https' or t == 'socks5':
    sorted_useful_proxy_list = sorted(useful_proxy_list.iteritems(),
                                      key=operator.itemgetter(1))
    # Write useful proxies
    with open(save_file_useful, 'wb') as f:
        for proxy, elapsed in sorted_useful_proxy_list:
            # print proxy, elapsed
            f.write(proxy + '\n')

    # Calculate error
    useful_rate = len(useful_proxy_list) * 0.1 / len(result)
    print "\n--------------------------------------------------"
    print "Useful rate is %s" % useful_rate
    print "--------------------------------------------------"
